/**
 * Jaxson ajax
 *
 * Copyright Remedy Interactive, licensed under Apache version 2 license:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0.html
 *
 * This notice must remain in all java source files.
 */
package org.jaxson.struts.encoder;

import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jaxson.struts.encoder.csv.CsvAnnotationCache;
import org.jaxson.struts.encoder.csv.CsvFieldRenderer;
import org.jaxson.struts.encoder.csv.CsvAnnotationCache.CsvFieldDescriptor;

/**
 * @author Joe Maisel
 *
 */
public class CsvEncoder extends ResponseEncoder
{
	private static final Log lager = LogFactory.getLog( CsvEncoder.class );
	
	/**
	 * @see org.jaxson.struts.encoder.ResponseEncoder#encode(java.io.Serializable)
	 */
	@Override
	public void encode( Serializable model ) throws EncodingException
	{
		if( !(model instanceof List<?>) )
			throw new IllegalArgumentException( "CSV Response Encoding can only be performed on classes extending java.util.List." );
		
		List<?> l = (List<?>)model;
		
		lager.info(  "model:" + l );
		lager.info( "size:" + l.size() );
		
		if( l == null || l.size() == 0 )
			return;
		
		try
		{
			// parse annotations and cache them
			Object o = l.get(0);
			CsvAnnotationCache.parse( o.getClass() );
			
			lager.info(  o.getClass() );
			
			List<CsvFieldDescriptor> desc = CsvAnnotationCache.get( o.getClass() );
			List<CsvFieldRenderer> renderers = new ArrayList<CsvFieldRenderer>();
			
			lager.info( "desc.size()=" + desc.size() );
			
			// Render titles, create renderers for values
			for( int i=0; i<desc.size(); i++ )
			{
				CsvFieldDescriptor d = desc.get( i );
				CsvFieldRenderer r = (CsvFieldRenderer)d.annotation.renderer().newInstance();
				renderers.add( r );
				
				String s = r.title( d.propertyName, i ) + (i<desc.size()-1?',':"");
				write( s.getBytes() );
				
				lager.info( "title: " + s );
			}
			
			write( "\n".getBytes() );
			
			// render data
			for( int row=0; row < l.size(); row++ )
			{
				for( int col=0; col<renderers.size(); col++ )
				{
					CsvFieldDescriptor d = desc.get( col );
					CsvFieldRenderer r = renderers.get( col );
					Object value = d.getter.invoke( l.get(row) );
					
					String s = r.value( value, d.propertyName, row, col ) + (col<renderers.size()-1?',':"");
					write( s.getBytes() );
				}
				
				write( "\n".getBytes() );
			}
		}
		catch( SecurityException e )
		{
			e.printStackTrace();
		}
		catch( NoSuchMethodException e )
		{
			e.printStackTrace();
		}
		catch( InstantiationException e )
		{
			e.printStackTrace();
		}
		catch( IllegalAccessException e )
		{
			e.printStackTrace();
		}
		catch( IllegalArgumentException e )
		{
			e.printStackTrace();
		}
		catch( InvocationTargetException e )
		{
			e.printStackTrace();
		}
		catch( IOException e )
		{
			e.printStackTrace();
		}
	}
}
